package org.xmap.ui.control;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

import org.xmap.app.Env;
import org.xmap.ui.Theme;
import org.xmap.ui.UIUtil;
import org.xmap.ui.View;
import org.xmap.ui.ViewManager;
import org.xmap.ui.base.Event;
import org.xmap.ui.base.Rect;
import org.xmap.ui.base.Window;
import org.xmap.ui.listener.MenuListener;

/**
 * <p>菜单类，可以添加菜单和监听器，当菜单被选中的时候，回调监听器的方法。</p>
 * <p>菜单的设计为左侧可以有多级菜单，右侧只能有一个菜单，一般把所有的功能放到左侧，可以根据功能的不同给菜单分级，右侧菜单一般就是返回或退出。</p>
 * @author Zealot
 * @version 1.0
 */
public final class Menubar extends Window {

    /**
     * 当拥有子菜单的时候，左侧显示的文字。
     */
    public static final String COMMAND_OPTION = "菜单";
    /**
     * 当拥有子菜单并且子菜单弹出的时候，左侧显示的文字。
     */
    public static final String COMMAND_CONFIRM = "确认";
    /**
     * 当拥有子菜单并且子菜单弹出的时候，右侧显示的文字。
     */
    public static final String COMMON_RETURN = "取消";
    /**
     * 菜单文字的颜色。
     */
    private int textColor;
    /**
     * 子菜单选中的背景颜色。
     */
    private int submenuFocusedBackgroundColor;
    /**
     * 菜单的监听器。
     */
    private MenuListener listener;
    /**
     * 左右文字的偏移，由于菜单栏的高度是可变的，而且由于不同设备的文字大小都不一样，为了正确显示左右的文字，需要在运行时计算出这个偏移量。
     */
    private int xyOffset;
    /**
     * 是否弹出子菜单。
     */
    private boolean menuPop; // 这个可以优化
    /**
     * 显示在左侧的文字。
     */
    private String leftText;
    /**
     * 显示在右侧的文字。
     */
    private String rightText;
    /**
     * 是否处于临时状态。
     */
    private boolean temporary; // 这个可以优化
    /**
     * 临时状态下的左菜单。
     */
    private String leftText2;
    /**
     * 临时状态下的右菜单。
     */
    private String rightText2;
    /**
     * 当前菜单栏的子菜单。
     */
    private Menu submenu;
    /**
     * 右边菜单，由于只会有一个，所以只保存菜单的文字就可以了。
     */
    private String rightMenu;
    /**
     * 左侧菜单的触笔响应区域。
     */
    private Rect leftMenuRect;
    /**
     * 右侧菜单的触笔响应区域。
     */
    private Rect rightMenuRect;

    /**
     * 指定拥有该菜单栏的视图和监听器的构造函数。
     * @param v View 拥有该菜单栏的视图。
     * @param listener MenuListener 监听器，用于响应菜单。
     */
    public Menubar(View v, MenuListener listener) {
        super(0, v.getRect().height, v.getRect().width, 0, Window.ORIENT_LEFT_DOWN);
        super.setShow(false);
        this.textColor = 0x0;
        this.submenuFocusedBackgroundColor = 0xff0000;
        this.listener = listener;
        this.xyOffset = 0;
        this.menuPop = false;
        this.leftText = null;
        this.rightText = null;
        this.temporary = false;
        this.leftText2 = null;
        this.rightText2 = null;
        this.submenu = new Menu();
        this.rightMenu = null;
        this.setEnableLeftMenu(true);
        this.leftMenuRect = new Rect(this.getRect().leftUp, 0, this.getRect().height);
        this.rightMenuRect = new Rect(this.getRect().leftUp.x + this.getRect().width, this.getRect().leftUp.y, 0, this.getRect().height);
    }

    /**
     * 设置窗口是否可用。
     * @param enable boolean 是否可用。
     */
    public final void setEnableLeftMenu(boolean enable) {
        if (enable) {
            super.state |= Window.STATE_MENUBAR_ENABLE_LEFT_MENU;
        } else {
            super.state &= ~Window.STATE_MENUBAR_ENABLE_LEFT_MENU;
        }
    }

    /**
     * 获得当前窗口是否可用。
     * @return boolean 是否可用。
     */
    public final boolean getEnableLeftMenu() {
        return (super.state & Window.STATE_MENUBAR_ENABLE_LEFT_MENU) != 0;
    }

    /**
     * 重新设置窗口的区域
     * @param leftUpX int 窗口左上角坐标
     * @param leftUpY int 窗口右上角坐标
     * @param width int 窗口宽度
     * @param height int 窗口高度
     */
    public void setRect(int leftUpX, int leftUpY, int width, int height) {
        super.setRect(leftUpX, leftUpY, width, height);
        this.xyOffset = (height - Env.instance.defaultFontHeight + 1) >> 1;
        if (this.xyOffset < 1) {
            this.xyOffset = 1;
        }
        int leftMenuRectWidth = this.leftMenuRect.width;
        int rightMenuRectWidth = this.rightMenuRect.width;
        this.leftMenuRect.setRect(this.getRect().leftUp.x, this.getRect().leftUp.y, leftMenuRectWidth, height);
        this.rightMenuRect.setRect(this.getRect().leftUp.x + width - rightMenuRectWidth, this.getRect().leftUp.y,
                                   rightMenuRectWidth, height);
    }

    /**
     * 设置文字的颜色。
     * @param color int 文字的颜色。
     */
    public void setTextColor(int color) {
        this.textColor = color;
    }

    /**
     * 获得文字的颜色。
     * @return int 文字的颜色。
     */
    public int getTextColor() {
        return this.textColor;
    }

    /**
     * 设置子菜单被选中的背景颜色。
     * @param submenuFocusedBackgroundColor int 子菜单被选中的背景颜色。
     */
    public void setSubmenuFocusedBackgroundColor(int submenuFocusedBackgroundColor) {
        this.submenuFocusedBackgroundColor = submenuFocusedBackgroundColor;
    }

    /**
     * 获得子菜单被选中的背景颜色。
     * @return int
     */
    public int getSubmenuFocusedBackgroundColor() {
        return this.submenuFocusedBackgroundColor;
    }

    /**
     * 设置菜单监听器。
     * @param listener MenuListener 监听器。
     */
    public void setListener(MenuListener listener) {
        this.listener = listener;
    }

    /**
     * 获得菜单监听器。
     * @return MenuListener 监听器。
     */
    public MenuListener getListener() {
        return this.listener;
    }

    /**
     * 获得当前菜单是否弹出子菜单。
     * @return boolean 是否弹出子菜单。
     */
    public boolean getMenuPop() {
        return this.menuPop;
    }

    /**
     * 添加菜单到左侧。
     * @param text String 菜单的文字。
     */
    public void addLeftMenu(String text) {
        if (text != null) {
            this.submenu.addMenuItem(text);
            if (this.submenu.itemCount() == 1) {
                this.setLeftText(text);
            } else if (this.submenu.itemCount() == 2) {
                if (!this.menuPop) {
                    this.setLeftText(Menubar.COMMAND_OPTION);
                }
            }
            this.menuChanged();
        }
    }

    /**
     * 添加指定名称的菜单和子菜单到左侧菜单组。
     * @param text String 菜单名称。
     * @param subCommand String[] 子菜单名称数组。
     */
    public final void addLeftMenu(String text, String[] subCommand) {
        if (text != null) {
            Menu m = new Menu();
            for (int i = 0; i < subCommand.length; i++) {
                m.addMenuItem(subCommand[i]);
            }
            this.submenu.addMenuItem(text, m);
            if (this.submenu.itemCount() == 1) {
                this.setLeftText(text);
            } else if (this.submenu.itemCount() == 2) {
                if (!this.menuPop) {
                    this.setLeftText(Menubar.COMMAND_OPTION);
                }
            }
            this.menuChanged();
        }
    }

    /**
     * 修改菜单的名字。
     * @param from String 修改前的菜单名。
     * @param to String 修改后的菜单名。
     */
    public void changeLeftMenu(String from, String to) {
        if (from != null && to != null && !from.equals(to)) {
            this.submenu.changeMenuItem(from, to);
            if (this.submenu.itemCount() == 1 && this.leftText.equals(from)) {
                this.setLeftText(to);
            }
        }
    }

    /**
     * 把指定菜单设置为左侧菜单。
     * @param m Menu 菜单。
     */
    public void setLeftMenu(Menu m) {
        if (m != null) {
            this.submenu = m;
            if (this.submenu.itemCount() == 1) {
                this.setLeftText(this.submenu.getItemByIndex(0).getText());
            } else if (this.submenu.itemCount() > 1) {
                this.setLeftText(Menubar.COMMAND_OPTION);
            }
            this.menuChanged();
        }
    }

    /**
     * 从左侧菜单移除指定的菜单。
     * @param text String 菜单名字。
     * @return boolean 是否移除成功。
     */
    public boolean removeLeftMenu(String text) {
        if (text != null) {
            boolean result = this.submenu.removeMenuItem(text);
            if (result) {
                if (this.submenu.itemCount() == 0) {
                    this.menuPop = false;
                    this.setLeftText(null);
                    this.setRightText(this.rightMenu);
                } else if (this.submenu.itemCount() == 1) {
                    this.menuPop = false;
                    this.setLeftText(this.submenu.getItemByIndex(0).getText());
                    this.setRightText(this.rightMenu);
                }
                this.menuChanged();
            }
            return result;
        }
        return false;
    }

    /**
     * 设置右侧菜单名字。
     * @param text String 菜单名字。
     */
    public void setRightMenu(String text) {
        this.rightMenu = text;
        if (!this.getMenuPop()) {
            this.setRightText(text);
        }
        this.menuChanged();
    }

    /**
     * 清除所有的菜单。
     */
    public void removeAll() {
        this.submenu.removeAll();
        this.setLeftText(null);
        this.setRightText(this.rightMenu);
        this.menuChanged();
    }

    /**
     * 设置成临时状态。
     * @param temporary boolean 是否设置成临时状态。
     * @param leftText String 临时状态下的左菜单。
     * @param rightText String 临时状态下的右菜单。
     */
    public void setTemporary(boolean temporary, String leftText, String rightText) {
        this.temporary = temporary;
        this.leftText2 = leftText;
        this.rightText2 = rightText;
        this.menuChanged();
        int width = 0;

        if (leftText != null) {
            width = Env.instance.defaultFont.stringWidth(leftText);
        }
        this.leftMenuRect.width = width + (xyOffset << 1);

        if (rightText != null) {
            width = Env.instance.defaultFont.stringWidth(rightText);
        }
        this.rightMenuRect.width = width + (xyOffset << 1);
        this.rightMenuRect.leftUp.x = this.getRect().leftUp.x + this.getRect().width - this.rightMenuRect.width;
    }

    /**
     * 返回是否处于临时状态。
     * @return boolean 临时状态。
     */
    public boolean getTemporary() {
        return this.temporary;
    }

    /**
     * 绘制函数。
     * @param g Graphics 图形句柄。
     */
    public void draw(Graphics g) {
        g.setFont(Env.instance.defaultFont);
        if (this.leftText != null || this.rightText != null || this.leftText2 != null || this.rightText2 != null) {
            if (Theme.instance.menubarBackground != null) {
                g.drawImage(Theme.instance.menubarBackground, this.getRect().width >> 1,
                            this.getRect().height >> 1, Graphics.VCENTER | Graphics.HCENTER);
            }
        }

        // 如果启用左侧菜单，则显示左侧菜单，否则不显示
        if (this.getEnable()) {
            if (!this.temporary) {
                if (this.getEnableLeftMenu()) {
                    if (this.menuPop) {
                        this.drawSubmenu(g, this.submenu);
                    }
                }
                g.setColor(Theme.instance.menubarTextColor);
                if (this.getEnableLeftMenu()) {
                    if (this.leftText != null) {
                        UIUtil.draw(g, this.leftText, this.xyOffset, this.getRect().height >> 1, Graphics.LEFT, Graphics.VCENTER);
                    }
                }
                if (this.rightText != null) {
                    UIUtil.draw(g, this.rightText, this.getRect().width - this.xyOffset, this.getRect().height >> 1,
                                Graphics.RIGHT, Graphics.VCENTER);
                }
            } else {
                g.setColor(Theme.instance.menubarTextColor);
                if (this.getEnableLeftMenu()) {
                    if (this.leftText2 != null) {
                        UIUtil.draw(g, this.leftText2, this.xyOffset, this.getRect().height >> 1, Graphics.LEFT, Graphics.VCENTER);
                    }
                }
                if (this.rightText2 != null) {
                    UIUtil.draw(g, this.rightText2, this.getRect().width - this.xyOffset, this.getRect().height >> 1,
                                Graphics.RIGHT, Graphics.VCENTER);
                }
            }
        }
    }

    /**
     * 按键事件处理函数，只处理导航键、中间键和左右软键。
     * @param flag boolean 是按下还是抬起。
     * @param keyCode int 按键代码。
     * @param gameAction int 动作代码。
     * @return boolean 是否处理该事件。
     */
    public boolean keyEvent(boolean flag, int keyCode, int gameAction) {
        if (flag) {
            if (keyCode >= Canvas.KEY_NUM1 && keyCode <= Canvas.KEY_NUM9) {
                if (this.pressNumberKey(keyCode)) {
                    return true;
                }
            }

            // 如果启用左侧菜单，则相应事件，否则不响应
            if (this.getEnableLeftMenu()) {
                switch (gameAction) {
                case Canvas.UP:
                    if (this.menuPop) {
                        this.submenuUp(this.submenu);
                        return true;
                    }
                case Canvas.DOWN:
                    if (this.menuPop) {
                        this.submenuDown(this.submenu);
                        return true;
                    }
                case Canvas.LEFT:
                    if (this.menuPop) {
                        boolean result = this.unexpandMenu(this.submenu);
                        if (result) { // 最顶层菜单，让菜单消失
                            this.pressRightSoftKey();
                        }
                        return true;
                    }
                case Canvas.RIGHT:
                    if (this.menuPop) {
                        this.expandMenu(this.submenu);
                        return true;
                    }
                case Canvas.FIRE:

                    // 三星的机器比较奇怪，左右软件的gameAction将会是FIRE
                    if (keyCode != Env.instance.leftSoftKey && keyCode != Env.instance.leftSoftKeySnd &&
                        keyCode != Env.instance.rightSoftKey && keyCode != Env.instance.rightSoftKeySnd) {
                        if (this.menuPop) {
                            return this.pressLeftSoftKey();
                        }
                    }
                }

                if (keyCode == Env.instance.leftSoftKey || -Math.abs(keyCode) == Env.instance.leftSoftKeySnd) {
                    if (gameAction != Canvas.DOWN) {
                        return this.pressLeftSoftKey();
                    }
                } else if (keyCode == Env.instance.rightSoftKey || -Math.abs(keyCode) == Env.instance.rightSoftKeySnd) {
                    return this.pressRightSoftKey();
                }
            } else {
                if (keyCode == Env.instance.rightSoftKey || -Math.abs(keyCode) == Env.instance.rightSoftKeySnd) {
                    return this.pressRightSoftKey();
                }
            }
        }

        if (this.getTemporary()) {
            return true;
        }

        return false;
    }

    /**
     * 触笔事件处理函数。
     * @param ev Event 触笔事件。
     * @return boolean 是否处理该事件。
     */
    public boolean pointerEvent(Event ev) {
        boolean result = false;
        switch (ev.type) {
        case Event.POINTER_PRESSED:
            if (this.getRect().collideWith(ev.param1, ev.param2)) { // 菜单栏内部
                result = true;
            } else { //菜单栏外面
                if (this.menuPop) {
                    // 如果有子菜单, 则需要弹出或收起子菜单, 同时返回true
                    int top = this.submenu.itemCount() * Env.instance.defaultFontHeight;
                    if (Theme.instance.submenuCornerLU != null) {
                        top += (Theme.instance.submenuCornerLU.getHeight() << 1);
                    }
                    result = this.submenuPointerPressed(this.submenu, ev.param1, ev.param2 - (this.getRect().leftUp.y - top)); // 转换x，y坐标
                    if (!result) { // 触笔在菜单外面
                        if (this.menuPop) {
                            this.menuPop = false;
                            this.setLeftText(Menubar.COMMAND_OPTION);
                            this.setRightText(this.rightMenu);
                            this.closeSubMenu(this.submenu); // 收起子菜单
                            ViewManager.instance.requestRepaint();
                        }
                    }
                }
            }
            if (result) {
                super.setPointerSelected(true); // 记录菜单接受过触笔事件
            }
            break;
        case Event.POINTER_RELEASED:
            if (this.getPointerSelected()) {
                if (this.getRect().collideWith(ev.param1, ev.param2)) {
                    if (this.leftMenuRect.collideWith(ev.param1, ev.param2)) {
                        // 如果启用左侧菜单
                        if (this.getEnableLeftMenu()) {
                            result = this.pressLeftSoftKey();
                        }
                    } else if (this.rightMenuRect.collideWith(ev.param1, ev.param2)) {
                        result = this.pressRightSoftKey();
                    }
                } else {
                    if (this.menuPop) {
                        // 如果有子菜单, 则需要弹出或收起子菜单, 同时返回true
                        int top = this.submenu.itemCount() * Env.instance.defaultFontHeight;
                        if (Theme.instance.submenuCornerLU != null) {
                            top += (Theme.instance.submenuCornerLU.getHeight() << 1);
                        }
                        result = this.submenuPointerReleased(this.submenu, ev.param1, ev.param2 - (this.getRect().leftUp.y - top)); // 转换x，y坐标
                        if (result) {
                            this.menuPop = false;
                            if (this.submenu.itemCount() > 1) {
                                // 如果在commmandEvent函数里面删除了所有的子菜单, 然后再添加一个子菜单
                                // 那么左边的字样将会出现选项, 产生bug
                                this.setLeftText(Menubar.COMMAND_OPTION);
                            }
                            this.setRightText(this.rightMenu);
                            this.closeSubMenu(this.submenu); // 收起子菜单
                        }
                        ViewManager.instance.requestRepaint();
                    }
                }
            }
            super.setPointerSelected(false);
            break;
        case Event.POINTER_DRAGGED:
            if (super.getPointerSelected()) {
                // 如果启用左侧菜单
                if (this.getEnableLeftMenu()) {
                    if (!this.getRect().collideWith(ev.param1, ev.param2)) {
                        if (this.menuPop) {
                            // 如果有子菜单, 则需要弹出或收起子菜单, 同时返回true
                            int top = this.submenu.itemCount() * Env.instance.defaultFontHeight;
                            if (Theme.instance.submenuCornerLU != null) {
                                top += (Theme.instance.submenuCornerLU.getHeight() << 1);
                            }
                            this.submenuPointerPressed(this.submenu, ev.param1, ev.param2 - (this.getRect().leftUp.y - top)); // 转换x，y坐标
                        }
                    }
                }
                result = true;
            }
            break;
        }
        if (this.getTemporary()) {
            result = true;
        }
        return result;
    }

    /**
     * 按下数字键。
     * @param keyCode int 按键键值。
     * @return boolean 事件是否被处理。
     */
    private boolean pressNumberKey(int keyCode) {
        if (this.menuPop) { // 处理弹出菜单
            String response = this.menuResponse(this.submenu, keyCode);
            if (response != null) {
                this.listener.commandEvent(response, this);
                if (this.submenu.itemCount() > 1) {
                    // 如果在commmandEvent函数里面删除了所有的子菜单, 然后再添加一个子菜单
                    // 那么左边的字样将会出现选项, 产生bug
                    this.setLeftText(Menubar.COMMAND_OPTION);
                }
                this.setRightText(this.rightMenu);
                this.closeSubMenu(this.submenu);
                this.menuPop = false;
                ViewManager.instance.requestRepaint();
                return true;
            }
        }
        return false;
    }

    /**
     * 按下左软键。
     * @return boolean 事件是否被处理。
     */
    private boolean pressLeftSoftKey() {
        if (!this.temporary) {
            if (this.leftText != null) {
                if (this.submenu.itemCount() == 1) {
                    if (this.listener != null) {
                        this.listener.commandEvent(this.leftText, this);
                    }
                } else {
                    if (this.menuPop) { // 处理弹出菜单
                        String response = this.expandMenuAndResponse(this.submenu);
                        if (response != null) {
                            this.listener.commandEvent(response, this);
                            if (this.submenu.itemCount() > 1) {
                                // 如果在commmandEvent函数里面删除了所有的子菜单, 然后再添加一个子菜单
                                // 那么左边的字样将会出现选项, 产生bug
                                this.setLeftText(Menubar.COMMAND_OPTION);
                            }
                            this.setRightText(this.rightMenu);
                            this.closeSubMenu(this.submenu);
                            this.menuPop = false;
                        }
                    } else {
                        this.setLeftText(Menubar.COMMAND_CONFIRM);
                        this.setRightText(Menubar.COMMON_RETURN);
                        this.menuPop = true;
                    }
                    ViewManager.instance.requestRepaint();
                }
                return true;
            }
        } else {
            if (this.leftText2 != null) {
                if (this.listener != null) {
                    this.listener.commandEvent(this.leftText2, this);
                }
                if (this.submenu.itemCount() > 1) {
                    this.setLeftText(Menubar.COMMAND_OPTION);
                    this.setRightText(this.rightMenu);
                } else {
                    this.setLeftText(this.leftText);
                    this.setRightText(this.rightMenu);
                }
                this.temporary = false;
                ViewManager.instance.requestRepaint();
                return true;
            }
        }
        return false;
    }

    /**
     * 按下右软键。
     * @return boolean 事件是否被处理。
     */
    private boolean pressRightSoftKey() {
        if (!this.temporary) {
            if (this.menuPop) {
                boolean result = this.unexpandMenu(this.submenu);
                if (result) {
                    this.menuPop = false;
                    this.setLeftText(Menubar.COMMAND_OPTION);
                    this.setRightText(this.rightMenu);
                }
                ViewManager.instance.requestRepaint();
                return true;
            } else if (this.rightMenu != null) {
                if (this.listener != null) {
                    this.listener.commandEvent(this.rightMenu, this);
                }
                ViewManager.instance.requestRepaint();
                return true;
            }
        } else {
            if (this.rightText2 != null) {
                if (this.listener != null) {
                    this.listener.commandEvent(this.rightText2, this);
                }
                if (this.submenu.itemCount() > 1) {
                    this.setLeftText(Menubar.COMMAND_OPTION);
                    this.setRightText(this.rightMenu);
                } else {
                    this.setLeftText(this.leftText);
                    this.setRightText(this.rightMenu);
                }
                this.temporary = false;
                ViewManager.instance.requestRepaint();
                return true;
            }
        }
        return false;
    }

    /**
     * 指定菜单的选中项向上移动。
     * @param m Menu 菜单。
     */
    private void submenuUp(Menu m) {
        boolean submenuExpand = false;
        for (int i = 0; i < m.itemCount(); i++) {
            if (i == m.getSelectIndex()) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu()) {
                    if (mi.getExpand()) {
                        submenuExpand = true;
                        this.submenuUp(mi.getSubmenu());
                    }
                }
            }
        }
        if (!submenuExpand) {
            m.moveUp();
            ViewManager.instance.requestRepaint();
        }
    }

    /**
     * 指定菜单选中项向下移动。
     * @param m Menu 菜单。
     */
    private void submenuDown(Menu m) {
        boolean submenuExpand = false;
        for (int i = 0; i < m.itemCount(); i++) {
            if (i == m.getSelectIndex()) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu()) {
                    if (mi.getExpand()) {
                        submenuExpand = true;
                        this.submenuDown(mi.getSubmenu());
                    }
                }
            }
        }
        if (!submenuExpand) {
            m.moveDown();
            ViewManager.instance.requestRepaint();
        }
    }

    /**
     * 展开指定的菜单，如果没有子菜单，则无效。
     * @param m Menu 菜单。
     */
    private void expandMenu(Menu m) {
        int index = m.getSelectIndex();
        MenuItem mi = m.getItemByIndex(index);
        if (mi != null) {
            if (mi.hasSubmenu()) {
                if (mi.getExpand()) {
                    this.expandMenu(mi.getSubmenu());
                } else {
                    mi.setExpand(true);
                    ViewManager.instance.requestRepaint();
                }
            } else { // 找到最近的有子菜单的菜单项
                int offset = 1;
                int pos = 0;
                boolean finish = false;
                while (!finish) {
                    pos = index - offset;
                    MenuItem miu = m.getItemByIndex(pos);
                    if (miu != null) {
                        if (miu.hasSubmenu()) {
                            m.setSelectIndex(pos); // 选中miu菜单
                            miu.setExpand(true); // 展开miu菜单
                            ViewManager.instance.requestRepaint();
                            break;
                        }
                    }

                    pos = index + offset;
                    MenuItem mid = m.getItemByIndex(pos);
                    if (mid != null) {
                        if (mid.hasSubmenu()) {
                            m.setSelectIndex(pos); // 选中mid菜单
                            mid.setExpand(true); // 展开mid菜单
                            ViewManager.instance.requestRepaint();
                            break;
                        }
                    }

                    offset++;
                    if (miu == null && mid == null) {
                        finish = true;
                    }
                }
            }
        }
    }

    /**
     * 展开指定的菜单，如果可以展开，则返回空，如果不能展开，则返回选中的菜单的名字。
     * @param m Menu 菜单。
     * @return String 如果可以展开，这返回空，否则返回选中的菜单的名字。
     */
    private String expandMenuAndResponse(Menu m) {
        for (int i = 0; i < m.itemCount(); i++) {
            if (i == m.getSelectIndex()) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu()) {
                    if (mi.getExpand()) {
                        return this.expandMenuAndResponse(mi.getSubmenu());
                    } else {
                        mi.setExpand(true);
                        ViewManager.instance.requestRepaint();
                        return null;
                    }
                } else {
                    return mi.getText();
                }
            }
        }
        return null;
    }

    /**
     * 指定的菜单的按键响应，如果没有响应，则返回空，如果有响应，则返回选中的菜单的名字。
     * @param m Menu 菜单。
     * @param keyCode int 按键键值。
     * @return String 如果可以展开，这返回空，否则返回选中的菜单的名字。
     */
    private String menuResponse(Menu m, int keyCode) {
        int index = keyCode - Canvas.KEY_NUM1;
        MenuItem mi = m.getItemByIndex(m.getSelectIndex());
        if (mi.hasSubmenu() && mi.getExpand()) { // 当前选中的菜单有子菜单，交给子菜单处理
            return this.menuResponse(mi.getSubmenu(), keyCode);
        } else { // 当前菜单处理
            if (index < m.itemCount()) { // 当前菜单处理
                m.setSelectIndex(index);
                mi = m.getItemByIndex(index);
                if (mi.hasSubmenu()) { // 如果有子菜单
                    if (mi.getExpand()) {
                        return this.menuResponse(mi.getSubmenu(), keyCode);
                    } else {
                        mi.setExpand(true);
                        ViewManager.instance.requestRepaint();
                        return null;
                    }
                } else { // 没有子菜单，直接返回响应
                    return mi.getText();
                }
            }
        }
        return null;
    }

    /**
     * 收起指定菜单的最后一个菜单，返回是否保留原来的状态，如果没有菜单可以收起，则表明保留原来的状态，返回true，如果菜单已经收起，则表明不再是原来的状态，返回false。
     * @param m Menu 菜单。
     * @return boolean 如果没有菜单可以收起，则表明保留原来的状态，返回true，如果菜单已经收起，则表明不再是原来的状态，返回false。
     */
    private boolean unexpandMenu(Menu m) {
        for (int i = 0; i < m.itemCount(); i++) {
            if (i == m.getSelectIndex()) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu() && mi.getExpand()) {
                    boolean result = this.unexpandMenu(mi.getSubmenu());
                    if (result) {
                        mi.setExpand(false);
                        ViewManager.instance.requestRepaint();
                    }
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 处理指定菜单的触笔按下操作。
     * @param m Menu 菜单。
     * @param pX int 触笔横坐标。
     * @param pY int 触笔纵坐标。
     * @return boolean 触点是否在菜单内，true表明触点在菜单内，false表明触点在菜单外。
     */
    private boolean submenuPointerPressed(Menu m, int pX, int pY) {
        int fontHeight = Env.instance.defaultFontHeight;
        int x = 0;
        int y = 0;
        if (Theme.instance.submenuCornerLU != null) {
            x = Theme.instance.submenuCornerLU.getWidth();
            y = Theme.instance.submenuCornerLU.getHeight();
        }
        boolean result = false;
        Menu next = null;
        Rect r = new Rect(m.getRect());
        r.width += (x << 1);
        r.height += (y << 1);
        if (r.collideWith(pX, pY)) {
//            ViewManager.instance.debugPrint("press  pX:" + pX + " pY:" + pY + " 菜单内部.");
            pX -= x;
            pY -= y;
            if (m.getRect().collideWith(pX, pY)) { // 触点在当前菜单内部
                int index = pY / fontHeight;
                if (index >= 0 && index < m.itemCount()) {
                    m.setSelectIndex(index);
                    ViewManager.instance.requestRepaint();
                    for (int i = 0; i < m.itemCount(); i++) {
                        MenuItem mi = m.getItemByIndex(i);
                        if (mi.hasSubmenu()) {
                            mi.setExpand(false); // 收起所有的子菜单
                            this.closeSubMenu(mi.getSubmenu());
                        }
                    }
                    MenuItem mi = m.getItemByIndex(index);
                    if (mi.hasSubmenu()) {
                        mi.setExpand(true); // 打开选中的子菜单
                    }
                }
            }
            result = true;
        } else { // 不在当前菜单, 遍历子菜单, 看触点是否在子菜单
            ViewManager.instance.debugPrint("press  pX:" + pX + " pY:" + pY + " 菜单外部.");
            pX -= x;
            pY -= y;
            for (int i = 0; i < m.itemCount(); i++) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu() && mi.getExpand()) {
                    next = mi.getSubmenu();
                    int xOffset = m.getRect().width; // 转换x, y坐标;
                    int yOffset = (i + 1) * fontHeight - next.itemCount() * fontHeight - (y << 1);
                    result = this.submenuPointerPressed(next, pX - xOffset, pY - yOffset);
                    break;
                }
            }
        }
        // true:触点在菜单内 false:触点不在菜单内
        return result;
    }

    /**
     * 处理指定菜单的触笔释放操作。
     * @param m Menu 菜单。
     * @param pX int 触笔横坐标。
     * @param pY int 触笔纵坐标。
     * @return boolean 触点是否在菜单内，true表明触点在菜单内，false表明触点在菜单外。
     */
    private boolean submenuPointerReleased(Menu m, int pX, int pY) {
        int fontHeight = Env.instance.defaultFontHeight;
        int x = 0;
        int y = 0;
        if (Theme.instance.submenuCornerLU != null) {
            x = Theme.instance.submenuCornerLU.getWidth();
            y = Theme.instance.submenuCornerLU.getHeight();
        }
        boolean result = false;
        Menu next = null;
        Rect r = new Rect(m.getRect());
        r.width += (x << 1);
        r.height += (y << 1);
        if (r.collideWith(pX, pY)) {
//            System.out.print("release pX:" + pX + " pY:" + pY + " 菜单内部.");
            pX -= x;
            pY -= y;
            if (m.getRect().collideWith(pX, pY)) { // 触点在当前菜单内部
                int index = pY / fontHeight;
                if (index >= 0 && index < m.itemCount()) {
                    MenuItem mi = m.getItemByIndex(index);
                    if (mi.hasSubmenu()) {
                        result = false;
                    } else {
                        if (this.listener != null) {
                            this.listener.commandEvent(mi.getText(), this);
                        }
                        result = true;
                    }
                }
            }
        } else { // 不在当前菜单, 遍历子菜单, 看触点是否在子菜单
//            System.out.print("release pX:" + pX + " pY:" + pY + " 菜单外部.");
            pX -= x;
            pY -= y;
            for (int i = 0; i < m.itemCount(); i++) {
                MenuItem mi = m.getItemByIndex(i);
                if (mi.hasSubmenu() && mi.getExpand()) {
                    next = mi.getSubmenu();
                    int xOffset = m.getRect().width; // 转换x, y坐标;
                    int yOffset = (i + 1) * fontHeight - next.itemCount() * fontHeight - (y << 1);
                    result = this.submenuPointerReleased(next, pX - xOffset, pY - yOffset);
                    break;
                }
            }
        }
//        System.out.println("处理结果:" + result);
        // true:触点在菜单内 false:触点不在菜单内
        return result;
    }

    /**
     * 检测是否显示当前菜单，只要添加了菜单，就会显示，否则不显示。
     */
    private void menuChanged() {
        if (this.rightMenu != null || this.submenu.itemCount() > 0 || this.leftText2 != null || this.rightText2 != null) {
            super.setShow(true);
        } else {
            super.setShow(false);
        }
    }

    /**
     * 设置左侧显示的文字，同时重新计算左侧的触笔响应区域。
     * @param text String 左侧显示的文字。
     */
    private void setLeftText(String text) {
        int width = 0;
        if (text != null) {
            width = Env.instance.defaultFont.stringWidth(text);
        }
        this.leftText = text;
        this.leftMenuRect.width = width + (xyOffset << 1);
    }

    /**
     * 设置右侧显示的文字，同时重新计算右侧的触笔响应区域。
     * @param text String 右侧显示的文字。
     */
    private void setRightText(String text) {
        int width = 0;
        if (text != null) {
            width = Env.instance.defaultFont.stringWidth(text);
        }
        this.rightText = text;
        this.rightMenuRect.width = width + (xyOffset << 1);
        this.rightMenuRect.leftUp.x = this.getRect().leftUp.x + this.getRect().width - this.rightMenuRect.width;
    }

    /**
     * 绘制子菜单。
     * @param g Graphics 图形句柄。
     * @param m Menu 菜单。
     */
    private void drawSubmenu(Graphics g, Menu m) {
        int fontHeight = Env.instance.defaultFontHeight;
        int top = m.itemCount() * fontHeight;

        if (Theme.instance.submenuCornerLU != null) {
            top += Theme.instance.submenuCornerLU.getHeight();
        }

        g.translate(0, -top);
        Menu next = null;
        int submenuY = 0;
        int x = 0;
        for (int i = 0; i < m.itemCount(); i++) {
            if (i == m.getSelectIndex()) {
                g.setColor(Theme.instance.submenuFocusedBackgroundColor);
            } else {
                g.setColor(Theme.instance.submenuBackgroundColor);
            }
            int y = i * fontHeight;
            if (Theme.instance.submenuLeft != null) {
                g.fillRect(Theme.instance.submenuLeft.getWidth(), y, m.getRect().width, fontHeight);
            } else {
                g.fillRect(0, y, m.getRect().width, fontHeight);
            }
            MenuItem mi = m.getItemByIndex(i);
            String command = mi.getText();
            if (Theme.instance.submenuLeft != null) {
                x = Theme.instance.submenuLeft.getWidth();
            }
            if (i == m.getSelectIndex()) {
                g.setColor(Theme.instance.submenuFocusedTextColor);
            } else {
                g.setColor(Theme.instance.submenuTextColor);
            }
            // 左侧显示文字
            UIUtil.draw(g, (i + 1) + "." + command, x, y + (fontHeight >> 1), Graphics.LEFT, Graphics.VCENTER);
            // 居中
//            UIUtil.draw(g, i + "." + command, x + (m.getMaxTextWidth() >> 1), y + (fontHeight >> 1), Graphics.HCENTER, Graphics.VCENTER);
            if (mi.hasSubmenu()) {
                if (mi.getExpand()) {
                    next = mi.getSubmenu();
                    submenuY = (i + 1) * fontHeight;
                }
                if (Theme.instance.submenuMore != null) {
                    g.drawImage(Theme.instance.submenuMore, x + m.getRect().width - Theme.instance.submenuMore.getWidth(),
                                y + (fontHeight >> 1), Graphics.LEFT | Graphics.VCENTER);
                }
            }
        }
        // 绘制中间部分
        if (Theme.instance.submenuCornerLU != null && Theme.instance.submenuLeft != null && Theme.instance.submenuTop != null) {
            int step = Theme.instance.submenuLeft.getHeight();
            for (int i = 0; i + step <= top - Theme.instance.submenuCornerLU.getHeight(); i += step) {
                // 左侧
                g.drawImage(Theme.instance.submenuLeft, 0, i, Graphics.LEFT | Graphics.TOP);
                // 右侧
                g.drawImage(Theme.instance.submenuRight, Theme.instance.submenuLeft.getWidth() + m.getRect().width,
                            i, Graphics.LEFT | Graphics.TOP);
            }
            g.drawImage(Theme.instance.submenuLeft, 0,
                        top - Theme.instance.submenuCornerLU.getHeight() - Theme.instance.submenuLeft.getHeight(),
                        Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuRight,
                        Theme.instance.submenuLeft.getWidth() + m.getRect().width,
                        top - Theme.instance.submenuCornerLU.getHeight() - Theme.instance.submenuRight.getHeight(),
                        Graphics.LEFT | Graphics.TOP);
            // 上面中部
            step = Theme.instance.submenuTop.getWidth();
            for (int i = 0; i + step <= m.getRect().width; i += step) { // 顶部
                g.drawImage(Theme.instance.submenuTop, Theme.instance.submenuCornerLU.getWidth() + i,
                            -Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
                g.drawImage(Theme.instance.submenuBottom, Theme.instance.submenuCornerLU.getWidth() + i,
                            top - Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
            }
            g.drawImage(Theme.instance.submenuTop, Theme.instance.submenuCornerLU.getWidth() + m.getRect().width - step,
                        -Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuBottom, Theme.instance.submenuCornerLU.getWidth() + m.getRect().width - step,
                        top - Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuCornerLU, 0, -Theme.instance.submenuCornerLU.getHeight(), // 左上
                        Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuCornerRU, Theme.instance.submenuCornerLU.getWidth() + m.getRect().width, // 右上
                        -Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuCornerLD, 0, // 左下
                        top - Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
            g.drawImage(Theme.instance.submenuCornerRD, Theme.instance.submenuCornerLU.getWidth() + m.getRect().width, // 右下
                        top - Theme.instance.submenuCornerLU.getHeight(), Graphics.LEFT | Graphics.TOP);
        }

        if (next != null) {
            g.translate(x + m.getRect().width, submenuY);
            this.drawSubmenu(g, next);
            g.translate( -(x + m.getRect().width), -submenuY);
        }
        g.translate(0, top);
    }

    /**
     * 收起指定菜单下的所有子菜单。
     * @param m Menu 菜单。
     */
    private void closeSubMenu(Menu m) {
        for (int i = 0; i < m.itemCount(); i++) {
            MenuItem mi = m.getItemByIndex(i);
            if (mi.hasSubmenu()) {
                mi.setExpand(false);
                this.closeSubMenu(mi.getSubmenu());
            }
        }
    }
}
